home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / shell / dialog-0.000 / dialog-0 / dialog-0.6c / textbox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-17  |  20.1 KB  |  727 lines

  1. /*
  2.  *  textbox.c -- implements the text box
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  *
  6.  *  This program is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU General Public License
  8.  *  as published by the Free Software Foundation; either version 2
  9.  *  of the License, or (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include "dialog.h"
  22.  
  23. static void back_lines (int n);
  24. static void print_page (WINDOW * win, int height, int width);
  25. static void print_line (WINDOW * win, int row, int width);
  26. static char *get_line (void);
  27. static int get_search_term (WINDOW * win, char *search_term,
  28.                 int height, int width);
  29. static void print_position (WINDOW * win, int height, int width);
  30.  
  31. static int hscroll = 0, fd, file_size, bytes_read;
  32. static int begin_reached = 1, end_reached = 0, page_length;
  33. static char *buf, *page;
  34.  
  35. /*
  36.  * Display text from a file in a dialog box.
  37.  */
  38. int
  39. dialog_textbox (const char *title, const char *file, int height, int width)
  40. {
  41.     int i, x, y, cur_x, cur_y, fpos, key = 0, dir, temp, temp1;
  42. #ifdef HAVE_NCURSES
  43.     int passed_end;
  44. #endif
  45.     char search_term[MAX_LEN + 1], *tempptr, *found;
  46.     WINDOW *dialog, *text;
  47.  
  48.     search_term[0] = '\0';    /* no search term entered yet */
  49.  
  50.     /* Open input file for reading */
  51.     if ((fd = open (file, O_RDONLY)) == -1) {
  52.     endwin ();
  53.     fprintf (stderr,
  54.          "\nCan't open input file in dialog_textbox().\n");
  55.     exit (-1);
  56.     }
  57.     /* Get file size. Actually, 'file_size' is the real file size - 1,
  58.        since it's only the last byte offset from the beginning */
  59.     if ((file_size = lseek (fd, 0, SEEK_END)) == -1) {
  60.     endwin ();
  61.     fprintf (stderr, "\nError getting file size in dialog_textbox().\n");
  62.     exit (-1);
  63.     }
  64.     /* Restore file pointer to beginning of file after getting file size */
  65.     if (lseek (fd, 0, SEEK_SET) == -1) {
  66.     endwin ();
  67.     fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n");
  68.     exit (-1);
  69.     }
  70.     /* Allocate space for read buffer */
  71.     if ((buf = malloc (BUF_SIZE + 1)) == NULL) {
  72.     endwin ();
  73.     fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n");
  74.     exit (-1);
  75.     }
  76.     if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  77.     endwin ();
  78.     fprintf (stderr, "\nError reading file in dialog_textbox().\n");
  79.     exit (-1);
  80.     }
  81.     buf[bytes_read] = '\0';    /* mark end of valid data */
  82.     page = buf;            /* page is pointer to start of page to be displayed */
  83.  
  84.     /* center dialog box on screen */
  85.     x = (COLS - width) / 2;
  86.     y = (LINES - height) / 2;
  87.  
  88. #ifdef HAVE_NCURSES
  89.     if (use_shadow)
  90.     draw_shadow (stdscr, y, x, height, width);
  91. #endif
  92.     dialog = newwin (height, width, y, x);
  93.     mouse_setbase (x, y);
  94.     keypad (dialog, TRUE);
  95.  
  96.     /* Create window for text region, used for scrolling text */
  97.     text = subwin (dialog, height - 4, width - 2, y + 1, x + 1);
  98.  
  99.     keypad (text, TRUE);
  100.  
  101.     /* register the new window, along with its borders */
  102.     mouse_mkbigregion (0, 0, height - 2, width, 1, 0, 2 /* not normal */ );
  103.     draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr);
  104.  
  105.     wattrset (dialog, border_attr);
  106.     wmove (dialog, height - 3, 0);
  107.     waddch (dialog, ACS_LTEE);
  108.     for (i = 0; i < width - 2; i++)
  109.     waddch (dialog, ACS_HLINE);
  110.     wattrset (dialog, dialog_attr);
  111.     waddch (dialog, ACS_RTEE);
  112.     wmove (dialog, height - 2, 1);
  113.     for (i = 0; i < width - 2; i++)
  114.     waddch (dialog, ' ');
  115.  
  116.     if (title != NULL) {
  117.     wattrset (dialog, title_attr);
  118.     wmove (dialog, 0, (width - strlen (title)) / 2 - 1);
  119.     waddch (dialog, ' ');
  120.     waddstr (dialog, title);
  121.     waddch (dialog, ' ');
  122.     }
  123.     print_button (dialog, " EXIT ", height - 2, width / 2 - 4, TRUE);
  124.     wnoutrefresh (dialog);
  125.     getyx (dialog, cur_y, cur_x);    /* Save cursor position */
  126.  
  127.     /* Print first page of text */
  128.     attr_clear (text, height - 4, width - 2, dialog_attr);
  129.     print_page (text, height - 4, width - 2);
  130.     print_position (dialog, height, width);
  131.     wmove (dialog, cur_y, cur_x);    /* Restore cursor position */
  132.     wrefresh (dialog);
  133.  
  134.     while ((key != ESC) && (key != '\n')) {
  135.     key = mouse_wgetch (dialog);
  136.     switch (key) {
  137.     case M_EVENT + 'E':
  138.     case 'E':        /* Exit */
  139.     case 'e':
  140.         delwin (dialog);
  141.         free (buf);
  142.         close (fd);
  143.         return 0;
  144.     case 'g':        /* First page */
  145.     case KEY_HOME:
  146.         if (!begin_reached) {
  147.         begin_reached = 1;
  148.         /* First page not in buffer? */
  149.         if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  150.             endwin ();
  151.             fprintf (stderr,
  152.               "\nError moving file pointer in dialog_textbox().\n");
  153.             exit (-1);
  154.         }
  155.         if (fpos > bytes_read) {    /* Yes, we have to read it in */
  156.             if (lseek (fd, 0, SEEK_SET) == -1) {
  157.             endwin ();
  158.             fprintf (stderr, "\nError moving file pointer in "
  159.                  "dialog_textbox().\n");
  160.             exit (-1);
  161.             }
  162.             if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  163.             endwin ();
  164.             fprintf (stderr,
  165.                  "\nError reading file in dialog_textbox().\n");
  166.             exit (-1);
  167.             }
  168.             buf[bytes_read] = '\0';
  169.         }
  170.         page = buf;
  171.         print_page (text, height - 4, width - 2);
  172.         print_position (dialog, height, width);
  173.         wmove (dialog, cur_y, cur_x);    /* Restore cursor position */
  174.         wrefresh (dialog);
  175.         }
  176.         break;
  177.     case 'G':        /* Last page */
  178. #ifdef HAVE_NCURSES
  179.     case KEY_END:
  180. #endif
  181.         end_reached = 1;
  182.         /* Last page not in buffer? */
  183.         if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  184.         endwin ();
  185.         fprintf (stderr,
  186.               "\nError moving file pointer in dialog_textbox().\n");
  187.         exit (-1);
  188.         }
  189.         if (fpos < file_size) {    /* Yes, we have to read it in */
  190.         if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) {
  191.             endwin ();
  192.             fprintf (stderr,
  193.               "\nError moving file pointer in dialog_textbox().\n");
  194.             exit (-1);
  195.         }
  196.         if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  197.             endwin ();
  198.             fprintf (stderr,
  199.                  "\nError reading file in dialog_textbox().\n");
  200.             exit (-1);
  201.         }
  202.         buf[bytes_read] = '\0';
  203.         }
  204.         page = buf + bytes_read;
  205.         back_lines (height - 4);
  206.         print_page (text, height - 4, width - 2);
  207.         print_position (dialog, height, width);
  208.         wmove (dialog, cur_y, cur_x);    /* Restore cursor position */
  209.         wrefresh (dialog);
  210.         break;
  211.     case 'K':        /* Previous line */
  212.     case 'k':
  213.     case KEY_UP:
  214.         if (!begin_reached) {
  215.         back_lines (page_length + 1);
  216. #ifdef HAVE_NCURSES
  217.         /* We don't call print_page() here but use scrolling to ensure
  218.            faster screen update. However, 'end_reached' and
  219.            'page_length' should still be updated, and 'page' should
  220.            point to start of next page. This is done by calling
  221.            get_line() in the following 'for' loop. */
  222.         scrollok (text, TRUE);
  223.         wscrl (text, -1);    /* Scroll text region down one line */
  224.         scrollok (text, FALSE);
  225.         page_length = 0;
  226.         passed_end = 0;
  227.         for (i = 0; i < height - 4; i++) {
  228.             if (!i) {
  229.             /* print first line of page */
  230.             print_line (text, 0, width - 2);
  231.             wnoutrefresh (text);
  232.             } else
  233.             /* Called to update 'end_reached' and 'page' */
  234.             get_line ();
  235.             if (!passed_end)
  236.             page_length++;
  237.             if (end_reached && !passed_end)
  238.             passed_end = 1;
  239.         }
  240. #else
  241.         print_page (text, height - 4, width - 2);
  242. #endif
  243.         print_position (dialog, height, width);
  244.         wmove (dialog, cur_y, cur_x);    /* Restore cursor position */
  245.         wrefresh (dialog);
  246.         }
  247.         break;
  248.     case 'B':        /* Previous page */
  249.     case 'b':
  250.     case KEY_PPAGE:
  251.         if (begin_reached)
  252.         break;
  253.         back_lines (page_length + height - 4);
  254.         print_page (text, height - 4, width - 2);
  255.         print_position (dialog, height, width);
  256.         wmove (dialog, cur_y, cur_x);
  257.         wrefresh (dialog);
  258.         break;
  259.     case 'J':        /* Next line */
  260.     case 'j':
  261.     case KEY_DOWN:
  262.         if (!end_reached) {
  263.         begin_reached = 0;
  264.         scrollok (text, TRUE);
  265.         scroll (text);    /* Scroll text region up one line */
  266.         scrollok (text, FALSE);
  267.         print_line (text, height - 5, width - 2);
  268. #ifndef HAVE_NCURSES
  269.         wmove (text, height - 5, 0);
  270.         waddch (text, ' ');
  271.         wmove (text, height - 5, width - 3);
  272.         waddch (text, ' ');
  273. #endif
  274.         wnoutrefresh (text);
  275.         print_position (dialog, height, width);
  276.         wmove (dialog, cur_y, cur_x);    /* Restore cursor position */
  277.         wrefresh (dialog);
  278.         }
  279.         break;
  280.     case ' ':        /* Next page */
  281.     case KEY_NPAGE:
  282.         if (end_reached)
  283.         break;
  284.  
  285.         begin_reached = 0;
  286.         print_page (text, height - 4, width - 2);
  287.         print_position (dialog, height, width);
  288.         wmove (dialog, cur_y, cur_x);
  289.         wrefresh (dialog);
  290.         break;
  291.     case '0':        /* Beginning of line */
  292.     case 'H':        /* Scroll left */
  293.     case 'h':
  294.     case KEY_LEFT:
  295.         if (hscroll <= 0)
  296.         break;
  297.  
  298.         if (key == '0')
  299.         hscroll = 0;
  300.         else
  301.         hscroll--;
  302.         /* Reprint current page to scroll horizontally */
  303.         back_lines (page_length);
  304.         print_page (text, height - 4, width - 2);
  305.         wmove (dialog, cur_y, cur_x);
  306.         wrefresh (dialog);
  307.         break;
  308.     case 'L':        /* Scroll right */
  309.     case 'l':
  310.     case KEY_RIGHT:
  311.         if (hscroll >= MAX_LEN)
  312.         break;
  313.         hscroll++;
  314.         /* Reprint current page to scroll horizontally */
  315.         back_lines (page_length);
  316.         print_page (text, height - 4, width - 2);
  317.         wmove (dialog, cur_y, cur_x);
  318.         wrefresh (dialog);
  319.         break;
  320.     case '/':        /* Forward search */
  321.     case 'n':        /* Repeat forward search */
  322.     case '?':        /* Backward search */
  323.     case 'N':        /* Repeat backward search */
  324.         /* set search direction */
  325.         dir = (key == '/' || key == 'n') ? 1 : 0;
  326.         if (dir ? !end_reached : !begin_reached) {
  327.         if (key == 'n' || key == 'N') {
  328.             if (search_term[0] == '\0') {    /* No search term yet */
  329.             fprintf (stderr, "\a");        /* beep */
  330.             break;
  331.             }
  332.         } else
  333.             /* Get search term from user */
  334.             if (get_search_term (text, search_term, height - 4,
  335.                      width - 2) == -1) {
  336.             /* ESC pressed in get_search_term().
  337.                Reprint page to clear box */
  338.             wattrset (text, dialog_attr);
  339.             back_lines (page_length);
  340.             print_page (text, height - 4, width - 2);
  341.             wmove (dialog, cur_y, cur_x);
  342.             wrefresh (dialog);
  343.             break;
  344.         }
  345.         /* Save variables for restoring in case search term
  346.            can't be found */
  347.         tempptr = page;
  348.         temp = begin_reached;
  349.         temp1 = end_reached;
  350.         if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  351.             endwin ();
  352.             fprintf (stderr, "\nError moving file pointer in "
  353.                  "dialog_textbox().\n");
  354.             exit (-1);
  355.         }
  356.         fpos -= bytes_read;
  357.         /* update 'page' to point to next (previous) line before
  358.            forward (backward) searching */
  359.         back_lines (dir ? page_length - 1 : page_length + 1);
  360.         found = NULL;
  361.         if (dir)    /* Forward search */
  362.             while ((found = strstr (get_line (), search_term))
  363.                == NULL) {
  364.             if (end_reached)
  365.                 break;
  366.         } else        /* Backward search */
  367.             while ((found = strstr (get_line (), search_term))
  368.                == NULL) {
  369.             if (begin_reached)
  370.                 break;
  371.             back_lines (2);
  372.             }
  373.         if (found == NULL) {    /* not found */
  374.             fprintf (stderr, "\a");    /* beep */
  375.             /* Restore program state to that before searching */
  376.             if (lseek (fd, fpos, SEEK_SET) == -1) {
  377.             endwin ();
  378.             fprintf (stderr, "\nError moving file pointer in "
  379.                  "dialog_textbox().\n");
  380.             exit (-1);
  381.             }
  382.             if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  383.             endwin ();
  384.             fprintf (stderr, "\nError reading file in "
  385.                  "dialog_textbox().\n");
  386.             exit (-1);
  387.             }
  388.             buf[bytes_read] = '\0';
  389.             page = tempptr;
  390.             begin_reached = temp;
  391.             end_reached = temp1;
  392.             /* move 'page' to point to start of current page in order to
  393.                re-print current page. Note that 'page' always points to
  394.                start of next page, so this is necessary */
  395.             back_lines (page_length);
  396.         } else        /* Search term found */
  397.             back_lines (1);
  398.         /* Reprint page */
  399.         wattrset (text, dialog_attr);
  400.         print_page (text, height - 4, width - 2);
  401.         if (found != NULL)
  402.             print_position (dialog, height, width);
  403.         wmove (dialog, cur_y, cur_x);    /* Restore cursor position */
  404.         wrefresh (dialog);
  405.         } else        /* no need to find */
  406.         fprintf (stderr, "\a");        /* beep */
  407.         break;
  408.     case ESC:
  409.         break;
  410.     }
  411.     }
  412.  
  413.     delwin (dialog);
  414.     free (buf);
  415.     close (fd);
  416.     return -1;            /* ESC pressed */
  417. }
  418.  
  419. /*
  420.  * Go back 'n' lines in text file. Called by dialog_textbox().
  421.  * 'page' will be updated to point to the desired line in 'buf'.
  422.  */
  423. static void
  424. back_lines (int n)
  425. {
  426.     int i, fpos;
  427.  
  428.     begin_reached = 0;
  429.     /* We have to distinguish between end_reached and !end_reached
  430.        since at end of file, the line is not ended by a '\n'.
  431.        The code inside 'if' basically does a '--page' to move one
  432.        character backward so as to skip '\n' of the previous line */
  433.     if (!end_reached) {
  434.     /* Either beginning of buffer or beginning of file reached? */
  435.     if (page == buf) {
  436.         if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  437.         endwin ();
  438.         fprintf (stderr, "\nError moving file pointer in "
  439.              "back_lines().\n");
  440.         exit (-1);
  441.         }
  442.         if (fpos > bytes_read) {    /* Not beginning of file yet */
  443.         /* We've reached beginning of buffer, but not beginning of
  444.            file yet, so read previous part of file into buffer.
  445.            Note that we only move backward for BUF_SIZE/2 bytes,
  446.            but not BUF_SIZE bytes to avoid re-reading again in
  447.            print_page() later */
  448.         /* Really possible to move backward BUF_SIZE/2 bytes? */
  449.         if (fpos < BUF_SIZE / 2 + bytes_read) {
  450.             /* No, move less then */
  451.             if (lseek (fd, 0, SEEK_SET) == -1) {
  452.             endwin ();
  453.             fprintf (stderr, "\nError moving file pointer in "
  454.                  "back_lines().\n");
  455.             exit (-1);
  456.             }
  457.             page = buf + fpos - bytes_read;
  458.         } else {    /* Move backward BUF_SIZE/2 bytes */
  459.             if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR)
  460.             == -1) {
  461.             endwin ();
  462.             fprintf (stderr, "\nError moving file pointer "
  463.                  "in back_lines().\n");
  464.             exit (-1);
  465.             }
  466.             page = buf + BUF_SIZE / 2;
  467.         }
  468.         if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  469.             endwin ();
  470.             fprintf (stderr, "\nError reading file in back_lines().\n");
  471.             exit (-1);
  472.         }
  473.         buf[bytes_read] = '\0';
  474.         } else {        /* Beginning of file reached */
  475.         begin_reached = 1;
  476.         return;
  477.         }
  478.     }
  479.     if (*(--page) != '\n') {    /* '--page' here */
  480.         /* Something's wrong... */
  481.         endwin ();
  482.         fprintf (stderr, "\nInternal error in back_lines().\n");
  483.         exit (-1);
  484.     }
  485.     }
  486.     /* Go back 'n' lines */
  487.     for (i = 0; i < n; i++)
  488.     do {
  489.         if (page == buf) {
  490.         if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  491.             endwin ();
  492.             fprintf (stderr,
  493.               "\nError moving file pointer in back_lines().\n");
  494.             exit (-1);
  495.         }
  496.         if (fpos > bytes_read) {
  497.             /* Really possible to move backward BUF_SIZE/2 bytes? */
  498.             if (fpos < BUF_SIZE / 2 + bytes_read) {
  499.             /* No, move less then */
  500.             if (lseek (fd, 0, SEEK_SET) == -1) {
  501.                 endwin ();
  502.                 fprintf (stderr, "\nError moving file pointer "
  503.                      "in back_lines().\n");
  504.                 exit (-1);
  505.             }
  506.             page = buf + fpos - bytes_read;
  507.             } else {    /* Move backward BUF_SIZE/2 bytes */
  508.             if (lseek (fd, -(BUF_SIZE / 2 + bytes_read),
  509.                    SEEK_CUR) == -1) {
  510.                 endwin ();
  511.                 fprintf (stderr, "\nError moving file pointer"
  512.                      " in back_lines().\n");
  513.                 exit (-1);
  514.             }
  515.             page = buf + BUF_SIZE / 2;
  516.             }
  517.             if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  518.             endwin ();
  519.             fprintf (stderr, "\nError reading file in "
  520.                  "back_lines().\n");
  521.             exit (-1);
  522.             }
  523.             buf[bytes_read] = '\0';
  524.         } else {    /* Beginning of file reached */
  525.             begin_reached = 1;
  526.             return;
  527.         }
  528.         }
  529.     } while (*(--page) != '\n');
  530.     page++;
  531. }
  532.  
  533. /*
  534.  * Print a new page of text. Called by dialog_textbox().
  535.  */
  536. static void
  537. print_page (WINDOW * win, int height, int width)
  538. {
  539.     int i, passed_end = 0;
  540.  
  541.     page_length = 0;
  542.     for (i = 0; i < height; i++) {
  543.     print_line (win, i, width);
  544.     if (!passed_end)
  545.         page_length++;
  546.     if (end_reached && !passed_end)
  547.         passed_end = 1;
  548.     }
  549.     wnoutrefresh (win);
  550. }
  551.  
  552. /*
  553.  * Print a new line of text. Called by dialog_textbox() and print_page().
  554.  */
  555. static void
  556. print_line (WINDOW * win, int row, int width)
  557. {
  558.     int i, y, x;
  559.     char *line;
  560.  
  561.     line = get_line ();
  562.     line += MIN (strlen (line), hscroll);    /* Scroll horizontally */
  563.     wmove (win, row, 0);    /* move cursor to correct line */
  564.     waddch (win, ' ');
  565. #ifdef HAVE_NCURSES
  566.     waddnstr (win, line, MIN (strlen (line), width - 2));
  567. #else
  568.     line[MIN (strlen (line), width - 2)] = '\0';
  569.     waddstr (win, line);
  570. #endif
  571.  
  572.     getyx (win, y, x);
  573.     /* Clear 'residue' of previous line */
  574.     for (i = 0; i < width - x; i++)
  575.     waddch (win, ' ');
  576. }
  577.  
  578. /*
  579.  * Return current line of text. Called by dialog_textbox() and print_line().
  580.  * 'page' should point to start of current line before calling, and will be
  581.  * updated to point to start of next line.
  582.  */
  583. static char *
  584. get_line (void)
  585. {
  586.     int i = 0, fpos;
  587.     static char line[MAX_LEN + 1];
  588.  
  589.     end_reached = 0;
  590.     while (*page != '\n') {
  591.     if (*page == '\0') {
  592.         /* Either end of file or end of buffer reached */
  593.         if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  594.         endwin ();
  595.         fprintf (stderr, "\nError moving file pointer in "
  596.              "get_line().\n");
  597.         exit (-1);
  598.         }
  599.         if (fpos < file_size) {    /* Not end of file yet */
  600.         /* We've reached end of buffer, but not end of file yet,
  601.            so read next part of file into buffer */
  602.         if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) {
  603.             endwin ();
  604.             fprintf (stderr, "\nError reading file in get_line().\n");
  605.             exit (-1);
  606.         }
  607.         buf[bytes_read] = '\0';
  608.         page = buf;
  609.         } else {
  610.         if (!end_reached)
  611.             end_reached = 1;
  612.         break;
  613.         }
  614.     } else if (i < MAX_LEN)
  615.         line[i++] = *(page++);
  616.     else {
  617.         /* Truncate lines longer than MAX_LEN characters */
  618.         if (i == MAX_LEN)
  619.         line[i++] = '\0';
  620.         page++;
  621.     }
  622.     }
  623.     if (i <= MAX_LEN)
  624.     line[i] = '\0';
  625.     if (!end_reached)
  626.     page++;            /* move pass '\n' */
  627.  
  628.     return line;
  629. }
  630.  
  631. /*
  632.  * Display a dialog box and get the search term from user
  633.  */
  634. static int
  635. get_search_term (WINDOW * win, char *search_term, int height, int width)
  636. {
  637.     int i, x, y, input_x = 0, scroll = 0, key = 0;
  638.     int box_height = 3, box_width = 30;
  639.  
  640.     x = (width - box_width) / 2;
  641.     y = (height - box_height) / 2;
  642. #ifdef HAVE_NCURSES
  643.     if (use_shadow)
  644.     draw_shadow (win, y, x, box_height, box_width);
  645. #endif
  646.     draw_box (win, y, x, box_height, box_width, dialog_attr,
  647.           searchbox_border_attr);
  648.     wattrset (win, searchbox_title_attr);
  649.     wmove (win, y, x + box_width / 2 - 4);
  650.     waddstr (win, " Search ");
  651.  
  652.     box_width -= 2;
  653.     wmove (win, y + 1, x + 1);
  654.     wrefresh (win);
  655.     search_term[0] = '\0';
  656.     wattrset (win, searchbox_attr);
  657.     while (key != ESC) {
  658.     key = wgetch (win);
  659.     switch (key) {
  660.     case '\n':
  661.         if (search_term[0] != '\0')
  662.         return 0;
  663.         break;
  664.     case KEY_BACKSPACE:
  665.     case 127:
  666.         if (input_x || scroll) {
  667.         if (!input_x) {
  668.             scroll = scroll < box_width - 1 ?
  669.             0 : scroll - (box_width - 1);
  670.             wmove (win, y + 1, x + 1);
  671.             for (i = 0; i < box_width; i++)
  672.             waddch (win, search_term[scroll + input_x + i] ?
  673.                 search_term[scroll + input_x + i] : ' ');
  674.             input_x = strlen (search_term) - scroll;
  675.         } else
  676.             input_x--;
  677.         search_term[scroll + input_x] = '\0';
  678.         wmove (win, y + 1, input_x + x + 1);
  679.         waddch (win, ' ');
  680.         wmove (win, y + 1, input_x + x + 1);
  681.         wrefresh (win);
  682.         }
  683.         break;
  684.     case ESC:
  685.         break;
  686.     default:
  687.         if (isprint (key))
  688.         if (scroll + input_x < MAX_LEN) {
  689.             search_term[scroll + input_x] = key;
  690.             search_term[scroll + input_x + 1] = '\0';
  691.             if (input_x == box_width - 1) {
  692.             scroll++;
  693.             wmove (win, y + 1, x + 1);
  694.             for (i = 0; i < box_width - 1; i++)
  695.                 waddch (win, search_term[scroll + i]);
  696.             } else {
  697.             wmove (win, y + 1, input_x++ + x + 1);
  698.             waddch (win, key);
  699.             }
  700.             wrefresh (win);
  701.         }
  702.     }
  703.     }
  704.  
  705.     return -1;            /* ESC pressed */
  706. }
  707.  
  708. /*
  709.  * Print current position
  710.  */
  711. static void
  712. print_position (WINDOW * win, int height, int width)
  713. {
  714.     int fpos, percent;
  715.  
  716.     if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) {
  717.     endwin ();
  718.     fprintf (stderr, "\nError moving file pointer in print_position().\n");
  719.     exit (-1);
  720.     }
  721.     wattrset (win, position_indicator_attr);
  722.     percent = !file_size ?
  723.     100 : ((fpos - bytes_read + page - buf) * 100) / file_size;
  724.     wmove (win, height - 3, width - 9);
  725.     wprintw (win, "(%3d%%)", percent);
  726. }
  727.